﻿
using System.Collections.Generic;

namespace LxCFD
{
    public class TypicalEquationUnit : LinearSolver, ISolvableUnit// SolvableUnitBase
    {
        protected List<EquationBase> Equations = new List<EquationBase>();
        protected List<ConnectBase> Connects = new List<ConnectBase>();
        public void CreateUnit(List<EquationBase> scalars, List<ConnectBase> connects, SolverTypes solverTypes)
        {
            this.Equations = scalars;
            this.Connects = connects;
            SetAMGSolver(scalars, connects);
            this.SolverType = solverTypes;
        }

        protected void prepareMatirx()
        {
            MultiThreads.RunCalTasks((taskIndex) =>
            {
                foreach (var s in Equations) { s.Set_x_Bound(taskIndex); }
            });
            MultiThreads.RunCalTasks((taskIndex) =>
            {
                foreach (var s in Equations) { s.CalGradient(taskIndex); }
            });
            MultiThreads.RunCalTasks((taskIndex) =>
            {
                foreach (var s in Equations) { s.SetAb_Step1(taskIndex); }
                foreach (var c in Connects) { c.SetAb_Step1(taskIndex); }
            });
            MultiThreads.RunCalTasks((taskIndex) =>
            {
                foreach (var s in Equations) { s.SetAb_Step2(taskIndex); }
            });
        }
        protected void updateBounds()
        {
            MultiThreads.RunCalTasks((taskIndex) =>
            {
                foreach (var c in Connects) { c.Copy_xArray(taskIndex); }
            });
            MultiThreads.RunCalTasks((taskIndex) =>
            {
                foreach (var s in Equations) { s.CalResidual(taskIndex); }
            });
            MultiThreads.RunCalTasks((taskIndex) =>
            {
                foreach (var s in Equations) { s.Update_x_Bound(taskIndex); }
                foreach (var c in Connects) { c.Update_x_Bound(taskIndex); }
            });
        }
        public void SaveOldValue()
        {
            foreach (var s in Equations) { s.TransData.PrepareToSave(); }
            MultiThreads.RunCalTasks((taskIndex) =>
            {
                foreach (var s in Equations) { s.TransData.SaveOldValue(taskIndex); }
            });
        }
        public void Solve_Steady()
        {
            prepareMatirx();
            RelaxAndSolve(Equations, Connects);
            updateBounds();
        }
        public void Solve_ExplicitTransient()
        {
            prepareMatirx();
            MultiThreads.RunCalTasks((taskIndex) =>
            {
                foreach (var s in Equations) { s.TransData.SetAb_ExplicitTrans(taskIndex); }
            });
            SolveExplicit(Equations, Connects);
            updateBounds();
        }
        public void Solve_ImplicitTransient()
        {
            prepareMatirx();
            MultiThreads.RunCalTasks((taskIndex) =>
            {
                foreach (var s in Equations) { s.TransData.SetAb_ImplicitTrans(taskIndex); }
            });
            RelaxAndSolve(Equations, Connects);
            updateBounds();
        }
    }
}






//public void AddScalar<T>(T scalar) where T : MatrixBase
//{
//    scalars.Add(scalar);
//}
//public void AddConnect<T>(T scalar) where T : ConnectWallBase
//{
//    connects.Add(scalar);
//}
//public override List<TypicalMatrixUnit> SplitByConnectivity(ConnectivityAnalysisTool connectivityAnalysis)
//{
//    List<TypicalMatrixUnit> Units = new List<TypicalMatrixUnit>();
//    var pools = connectivityAnalysis.Analysis(scalars, connects);
//    foreach (var p in pools)
//    {
//        TypicalMatrixUnit u = new TypicalMatrixUnit();
//        foreach (int z in p.zonesIndex)
//        {
//            u.AddScalar(scalars[z]);
//        }
//        foreach (int c in p.contactsIndex)
//        {
//            u.AddConnect(connects[c]);
//        }

//        Units.Add(u);
//    }
//    return Units;
//}

// printResult(taskIndex);
//public override void CalResidual(int taskIndex)
//{
//    CalResidual(scalars, connects, taskIndex);
//}
//public double GetMaxNormalRc()
//{
//    return ResidualItem.GetMaxNormalRc(scalars);
//}
//string mes;
//double result;

//private void printResult(int taskIndex)
//{
//    foreach (var Axb in scalars)
//    {
//        TasksControl.Sync(taskIndex, () => this.mes = string.Format("{0};", Axb.zone.name));
//        foreach (var t in Axb.zone.BoundThreads)
//        {
//            StatisticTool.AddRange_VolumnWeighted(Axb.x, Axb.zone.cells, t.ThreadIndex, taskIndex);
//            TasksControl.FinishStatisticAndReset(taskIndex, StatisticTool.MakeResult_WeightedAverage, ref result);
//            TasksControl.Sync(taskIndex, () => mes += string.Format("{0}:{1};", t.name, result));
//        }
//        TasksControl.Sync(taskIndex, () => LxConsole.AddLine(LogTypes.计算, mes));
//        //FindError.FindNAN(Axb.x);
//    }
//}